/**
 * 
 */
package edu.hawaii.its381b.client;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.dom.client.AudioElement;
import com.google.gwt.dom.client.MediaElement;
import com.google.gwt.media.client.Audio;

/**
 * @author Longshot
 *
 */
public class CrabPlayer{

	private final int lastCrab =5,
	  leftSide = 0, rightSide = 50,
	  armLeftDownFacingLeft= 300, armRightDownFacingLeft = 100,
	  armLeftDownFacingRight= 0, armRightDownFacingRight = 200,
	  armLeftUpFacingLeft= 350, armRightUpFacingLeft = 150,
	  armLeftUpFacingRight= 50, armRightUpFacingRight = 250,
	  CrabSizepx = 50, offSetByOne=1;
	
private int crabSpeed, LocationX,LocationY, //This is the player location in reference to the game map
			CanvasLocationX,CanvasLocationY, //This is the player location in reference to the game canvas
			CanvasWidth,CanvasHeight,mapWidth,mapHeight,crabBoundary,
			crabMaxHealth, currentPlayedCrab,
			controlBarThickness,distanceFromMapEdge,
			crabCurrentHealth[] = new int[lastCrab+offSetByOne], crabFacing, 
			drawLegFrame, frameLegs, drawArmLeftFrame, drawArmRightFrame;
					   

private ImageElement crabLegs,
					 crabTail[] = new ImageElement[lastCrab+offSetByOne],
					 crabArms[] = new ImageElement[lastCrab+offSetByOne],
					 crabBody[] = new ImageElement[lastCrab+offSetByOne],
					 crabMouth,
					 crabEyes[] = new ImageElement[lastCrab+offSetByOne];
private Canvas canvas;
private boolean crabOnBorder = false, crabWentDown = true, canPlay = true;
private Audio walkSoundFX = Audio.createIfSupported();


public CrabPlayer(int startLocationX, int startLocationY, int startCanvasLocationX, int startCanvasLocationY,
				  int canvasWidthAmount, int canvasHeightAmount, int mapWidthAmount,int mapHeightAmount,
				  int crabBoundyAmount, int controlBarThicknessAmount, int distanceFromMapEdgeAmount,
				  int startSpeed, Canvas gameCanvas,int gameCrabMaxHealth){
	
	initializeCrabPlayer(
			startLocationX, startLocationY, startCanvasLocationX, startCanvasLocationY,
			canvasWidthAmount,  canvasHeightAmount,  mapWidthAmount, mapHeightAmount,
			crabBoundyAmount,  controlBarThicknessAmount,  distanceFromMapEdgeAmount,
			startSpeed, gameCanvas,gameCrabMaxHealth);
	loadEyes();
	loadMouth();
	loadBodies();
	loadTails();
	loadArms();
	loadLegs();
	loadSoundFX();
}

public void initializeCrabPlayer(int startLocationX, int startLocationY, int startCanvasLocationX, int startCanvasLocationY,
		  						 int canvasWidthAmount, int canvasHeightAmount, int mapWidthAmount,int mapHeightAmount,
		  						 int crabBoundyAmount, int controlBarThicknessAmount, int distanceFromMapEdgeAmount,
		  						 int startSpeed, Canvas gameCanvas,int gameCrabMaxHealth){
	canvas = gameCanvas;
	LocationX = startLocationX;
	LocationY = startLocationY;
	CanvasLocationX = startCanvasLocationX;
	CanvasLocationY = startCanvasLocationY;
	CanvasWidth = canvasWidthAmount;
	CanvasHeight = canvasHeightAmount;
	mapWidth = mapWidthAmount;
	mapHeight = mapHeightAmount;
	crabBoundary = crabBoundyAmount;
	controlBarThickness = controlBarThicknessAmount;
	distanceFromMapEdge = distanceFromMapEdgeAmount;
	crabSpeed = 0;
	crabFacing = rightSide;
	crabMaxHealth = gameCrabMaxHealth;
	currentPlayedCrab =1;
	
	for(int currentCrab = 1; currentCrab <= lastCrab; currentCrab++){
	crabCurrentHealth[currentCrab] = crabMaxHealth; 
	}

	frameLegs = 0;
}

public void walkFXTurnOn(){
	//the Can Play check safeguards against calling audio commands when no audio is available
	if(canPlay){
		walkSoundFX.play();					
	}
}

public void walkFXTurnOff(){
	//the Can Play check safeguards against calling audio commands when no audio is available
	if(canPlay){
		walkSoundFX.pause();					
	}
}

private void loadEyes(){
	SafeUri crabEyesURI = HermitCrabResources.INSTANCE.crabEyes().getSafeUri();
	crabEyes[1]= ImageElement.as((new Image(crabEyesURI)).getElement());
	SafeUri crabEyesURI2 = HermitCrabResources.INSTANCE.crabEyes().getSafeUri();
	crabEyes[2]= ImageElement.as((new Image(crabEyesURI2)).getElement());
	SafeUri crabEyesURI3 = HermitCrabResources.INSTANCE.crabEyes().getSafeUri();
	crabEyes[3]= ImageElement.as((new Image(crabEyesURI3)).getElement());
	SafeUri crabEyesURI4 = HermitCrabResources.INSTANCE.crabEyes().getSafeUri();
	crabEyes[4]= ImageElement.as((new Image(crabEyesURI4)).getElement());
	SafeUri crabEyesURI5 = HermitCrabResources.INSTANCE.crabEyesJewelled().getSafeUri();
	crabEyes[5]= ImageElement.as((new Image(crabEyesURI5)).getElement());
}

private void loadMouth(){
	SafeUri crabMouthURI = HermitCrabResources.INSTANCE.crabMouth().getSafeUri();
	crabMouth = ImageElement.as((new Image(crabMouthURI)).getElement());	
}

private void loadBodies(){
	SafeUri crabBodyURI = HermitCrabResources.INSTANCE.crabBody().getSafeUri();
	crabBody[1]= ImageElement.as((new Image(crabBodyURI)).getElement());
	SafeUri crabBodyURI2 = HermitCrabResources.INSTANCE.crabBody().getSafeUri();
	crabBody[2]= ImageElement.as((new Image(crabBodyURI2)).getElement());
	SafeUri crabBodyURI3 = HermitCrabResources.INSTANCE.crabBodyHidden().getSafeUri();
	crabBody[3]= ImageElement.as((new Image(crabBodyURI3)).getElement());
	SafeUri crabBodyURI4 = HermitCrabResources.INSTANCE.crabBodyElegant().getSafeUri();
	crabBody[4]= ImageElement.as((new Image(crabBodyURI4)).getElement());
	SafeUri crabBodyURI5 = HermitCrabResources.INSTANCE.crabBody().getSafeUri();
	crabBody[5]= ImageElement.as((new Image(crabBodyURI5)).getElement());
}

private void loadArms(){
	SafeUri crabArmsURI1 = HermitCrabResources.INSTANCE.crabArms().getSafeUri();
	crabArms[1]  = ImageElement.as((new Image(crabArmsURI1)).getElement());
	SafeUri crabArmsURI2 = HermitCrabResources.INSTANCE.crabArmsLeftHanded().getSafeUri();
	crabArms[2]  = ImageElement.as((new Image(crabArmsURI2)).getElement());
	SafeUri crabArmsURI3 = HermitCrabResources.INSTANCE.crabArmsHidden().getSafeUri();
	crabArms[3]  = ImageElement.as((new Image(crabArmsURI3)).getElement());
	SafeUri crabArmsURI4 = HermitCrabResources.INSTANCE.crabArmsElegant().getSafeUri();
	crabArms[4]  = ImageElement.as((new Image(crabArmsURI4)).getElement());
	SafeUri crabArmsURI5 = HermitCrabResources.INSTANCE.crabArms().getSafeUri();
	crabArms[5]  = ImageElement.as((new Image(crabArmsURI5)).getElement());
}

private void loadTails(){
	SafeUri crabTailURI = HermitCrabResources.INSTANCE.crabTail().getSafeUri();
	crabTail[1]  = ImageElement.as((new Image(crabTailURI)).getElement());
	SafeUri crabTailURI2 = HermitCrabResources.INSTANCE.crabTail().getSafeUri();
	crabTail[2]  = ImageElement.as((new Image(crabTailURI2)).getElement());
	SafeUri crabTailURI3 = HermitCrabResources.INSTANCE.crabTailHidden().getSafeUri();
	crabTail[3]  = ImageElement.as((new Image(crabTailURI3)).getElement());
	SafeUri crabTailURI4 = HermitCrabResources.INSTANCE.crabTailElegant().getSafeUri();
	crabTail[4]  = ImageElement.as((new Image(crabTailURI4)).getElement());
	SafeUri crabTailURI5 = HermitCrabResources.INSTANCE.crabTail().getSafeUri();
	crabTail[5]  = ImageElement.as((new Image(crabTailURI5)).getElement());
}

private void loadLegs(){
	SafeUri crabLegsURI = HermitCrabResources.INSTANCE.crabLegs().getSafeUri();
	crabLegs = ImageElement.as((new Image(crabLegsURI)).getElement());
}

private void loadSoundFX(){
	if (walkSoundFX == null) {
		//RootPanel.get().add(new Label("Audio is not supported by the browser"));
		canPlay= false;
	} else {
			AudioElement element = walkSoundFX.getAudioElement();
			String canPlayMP3 = element.canPlayType(AudioElement.TYPE_MP3);
			if(canPlayMP3.equalsIgnoreCase(MediaElement.CANNOT_PLAY)){
				//RootPanel.get().add(new Label("MP3 audio is not supported by the browser"));

				canPlay= false;
			} else {
			element.setSrc(HermitCrabResources.INSTANCE.crabWalk().getSafeUri().asString());
			walkSoundFX.setLoop(true);
			RootPanel.get().add(walkSoundFX);
			canPlay= true;
			}
	}
}
public int getSpeed() {
	return crabSpeed;
	}
public void setSpeed(int InputSpeed) {
	crabSpeed = InputSpeed;
	}

public int getLocationX() {
	return LocationX;
	}
public void  setLocationX(int InputLocationX) {
	this.LocationX = InputLocationX;
	}

public int getLocationY() {
	return this.LocationY;
	}
public void setLocationY(int InputLocationY) {
	this.LocationY = InputLocationY;
	}

public int getGridLocationX() {
	return (LocationX+(CrabSizepx/2))/CrabSizepx;
	}

public int getGridLocationY() {
	return (LocationY+(CrabSizepx/2))/CrabSizepx;
	}

public int getCanvasLocationX() {
	return this.CanvasLocationX;
	}
public void setCanvasLocationX(int InputCanvasLocationX) {
	this.CanvasLocationX = InputCanvasLocationX;
	}

public int getCanvasLocationY() {
	return this.CanvasLocationY;
	}
public void setCanvasLocationY(int InputCanvasLocationY) {
	this.CanvasLocationY = InputCanvasLocationY;
	}

public int getCrabHealth(int crabBeingPlayed){
	return 	crabCurrentHealth[crabBeingPlayed];
}

public void setCrabHealth(int crabBeingPlayed, int currentHealth){
	crabCurrentHealth[crabBeingPlayed] = currentHealth;
}

public void reduceCrabHealth(int crabBeingPlayed, int healthReduction){
	crabCurrentHealth[crabBeingPlayed] = crabCurrentHealth[crabBeingPlayed] -healthReduction;
	if (crabCurrentHealth[crabBeingPlayed] < 1){crabCurrentHealth[crabBeingPlayed] = 1;}
	updateCrabSpeed(crabBeingPlayed);
}

public void increaseCrabHealth(int crabBeingPlayed, int healthIncrease){
	crabCurrentHealth[crabBeingPlayed] = crabCurrentHealth[crabBeingPlayed] +healthIncrease;
	if (crabCurrentHealth[crabBeingPlayed] > crabMaxHealth){crabCurrentHealth[crabBeingPlayed] = crabMaxHealth;}
	updateCrabSpeed(crabBeingPlayed);
}

private void updateCrabSpeed(int crabBeingPlayed){
	crabSpeed = 9 - crabCurrentHealth[crabBeingPlayed]/100;
	if (crabSpeed < 1){crabSpeed = 0;}	
}

public boolean nextCrabCanBePlayed(){
	if(this.currentPlayedCrab < this.lastCrab){
		currentPlayedCrab++;
		return true;
	}else{
		return false;
	}
}

public int getCurrentCrab(){
			return currentPlayedCrab;
	}

 public int moveRight(Integer mapSpeed) {

	frameLegs = frameLegs +1;

	if(frameLegs>4){frameLegs = 0;}
	crabFacing = rightSide;
	if(mapSpeed <=2){	// Don't let the Crab move faster over reef.
		mapSpeed = mapSpeed -crabSpeed;
	}	
	crabOnBorder = crabIsOnBorder(mapSpeed, "Right");
	if(crabOnBorder){
		//Prevent the crab from passing the border.
		CanvasLocationX = CanvasWidth - crabBoundary-CrabSizepx;	
		}
	else {
		//Move crab
		this.CanvasLocationX = this.CanvasLocationX+= (mapSpeed + crabSpeed);
		}
	LocationX = LocationX+= (mapSpeed + crabSpeed);
	if (LocationX > (mapWidth-(CrabSizepx+(distanceFromMapEdge)))){
		LocationX = mapWidth-(CrabSizepx+(distanceFromMapEdge));
	}
	return this.CanvasLocationX;
	}

public int moveLeft(Integer mapSpeed) {
	frameLegs = frameLegs -1;
	if(frameLegs<0){frameLegs = 4;}
	crabFacing = leftSide;

	if(mapSpeed <=2){	// Don't let the Crab move faster over reef.
		mapSpeed = mapSpeed -crabSpeed;
	}
	
	//Prevent the crab from passing the border.
	crabOnBorder = crabIsOnBorder(mapSpeed, "Left");
	if(crabOnBorder){
		//Prevent the crab from passing the border.
		CanvasLocationX = crabBoundary;	
		}
	else {
		//Move crab
		this.CanvasLocationX = this.CanvasLocationX-= (mapSpeed + crabSpeed);
		}
	LocationX = LocationX-= (mapSpeed + crabSpeed);
	if (LocationX < distanceFromMapEdge){
		LocationX = distanceFromMapEdge;
	}
	return this.CanvasLocationX;
	}

public int moveDown(Integer mapSpeed) {
	frameLegs = frameLegs -1;
	if(frameLegs<0){frameLegs = 4;}
	crabWentDown = true;
	if(mapSpeed <=2){// Don't let the Crab move faster over reef.
		mapSpeed = mapSpeed -crabSpeed;
	}
	
	//Prevent the crab from passing the crab boundary.
	crabOnBorder = crabIsOnBorder(mapSpeed, "Down");
	if(crabOnBorder){
		//Prevent the crab from passing the border.
		CanvasLocationY = CanvasHeight - crabBoundary-CrabSizepx;	
		}
	else {
		//Move Crab
		this.CanvasLocationY = this.CanvasLocationY+= (mapSpeed + crabSpeed);
		}
	LocationY = LocationY+= (mapSpeed + crabSpeed);
	if (LocationY > mapHeight - (distanceFromMapEdge+CrabSizepx)){
		LocationY = mapHeight - (distanceFromMapEdge+CrabSizepx);
	}	
	return CanvasLocationY;
	}

public int moveUp(Integer mapSpeed) {
	frameLegs = frameLegs +1;
	crabWentDown = false;
	
	if(frameLegs>4){frameLegs = 0;}
	if(mapSpeed <=2){// Don't let the Crab move faster over reef.
		mapSpeed = mapSpeed -crabSpeed;
	}
	//Prevent the crab from passing the border.
	crabOnBorder = crabIsOnBorder(mapSpeed, "Up");
	if(crabOnBorder){
		CanvasLocationY = crabBoundary;	
		//LocationY = CanvasBorder;
		}
	else {
		this.CanvasLocationY = this.CanvasLocationY-= (mapSpeed + crabSpeed);
		}
	LocationY = LocationY-= (mapSpeed + crabSpeed);
	if (LocationY < distanceFromMapEdge){
		LocationY = distanceFromMapEdge;
	}	
	return CanvasLocationY;
	}

public boolean crabIsOnBorder(int mapSpeed, String direction){
	if (direction == "Up" && CanvasLocationY - (mapSpeed + crabSpeed) < crabBoundary) {
		return true;
		}
	if (direction == "Down" && CanvasLocationY + (mapSpeed + crabSpeed) > CanvasHeight - crabBoundary-CrabSizepx) {
		return true;
		}
	if (direction == "Left" && this.CanvasLocationX - (mapSpeed + crabSpeed) < crabBoundary) {
		return true;		
		}
	if (direction == "Right" && this.CanvasLocationX + (mapSpeed + crabSpeed) > CanvasWidth - crabBoundary-CrabSizepx) {
		return true;		
		}
	return false;	
}

private void updateLegFrame(){
		drawLegFrame = frameLegs * 50;
	
}

private void updateArmFrames(){
	if(crabFacing == leftSide){
		if(crabWentDown){
			drawArmLeftFrame = armLeftDownFacingLeft;
			drawArmRightFrame = armRightDownFacingLeft;
			if(crabSpeed > 4){drawArmLeftFrame = armLeftUpFacingLeft;
							  drawArmRightFrame = armRightUpFacingLeft;
			}
			if(crabSpeed > 7 && frameLegs > 2){drawArmLeftFrame = armLeftDownFacingLeft;
			  								  drawArmRightFrame = armRightDownFacingLeft;
			}
		}else{
			drawArmLeftFrame = armLeftDownFacingLeft;
			drawArmRightFrame = armRightDownFacingLeft;
			if(crabSpeed > 4){drawArmLeftFrame = armLeftUpFacingLeft;
			  				  drawArmRightFrame = armRightUpFacingLeft;
			}
			if(crabSpeed > 7 && frameLegs > 2){drawArmLeftFrame = armLeftDownFacingLeft;
											   drawArmRightFrame = armRightDownFacingLeft;
			}
		}
	}else{
		if(crabWentDown){
		drawArmLeftFrame = armLeftDownFacingRight;
		drawArmRightFrame = armRightDownFacingRight;
		if(crabSpeed > 4){drawArmLeftFrame = armLeftUpFacingRight;
							drawArmRightFrame = armRightUpFacingRight;
		}
		if(crabSpeed > 7 && frameLegs > 2){drawArmLeftFrame = armLeftDownFacingRight;
											drawArmRightFrame = armRightDownFacingRight;
		}
		}else{
			drawArmLeftFrame = armLeftDownFacingRight;
			drawArmRightFrame = armRightDownFacingRight;
			if(crabSpeed > 4){drawArmLeftFrame = armLeftUpFacingRight;
							drawArmRightFrame = armRightUpFacingRight;
			}
			if(crabSpeed > 7 && frameLegs > 2){drawArmLeftFrame = armLeftDownFacingRight;
							  					drawArmRightFrame = armRightDownFacingRight;
			}
		}
	}
}

public void draw(int crabOnBoard){
	currentPlayedCrab = crabOnBoard;
	updateLegFrame();
	updateArmFrames();
	canvas.getContext2d().clearRect(0, 0,CanvasWidth,CanvasHeight);
	
	//Legs
	canvas.getContext2d().drawImage(crabLegs,drawLegFrame,0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY, CrabSizepx,CrabSizepx);
	//Tail
	canvas.getContext2d().drawImage(crabTail[currentPlayedCrab],crabFacing,0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY, CrabSizepx,CrabSizepx);
	//LeftArm
	canvas.getContext2d().drawImage(crabArms[currentPlayedCrab],drawArmLeftFrame,0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY, CrabSizepx,CrabSizepx);
	//RightArm
	canvas.getContext2d().drawImage(crabArms[currentPlayedCrab],drawArmRightFrame,0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY, CrabSizepx,CrabSizepx);
	//Body
	canvas.getContext2d().drawImage(crabBody[currentPlayedCrab],crabFacing,0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY, CrabSizepx,CrabSizepx);
	//Mouth
	canvas.getContext2d().drawImage(crabMouth,(crabFacing*10)+(crabSpeed*50),0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY-crabSpeed/2, CrabSizepx,CrabSizepx);
	//Eyes
	canvas.getContext2d().drawImage(crabEyes[currentPlayedCrab],(crabFacing*10)+(crabSpeed*50),0,CrabSizepx,CrabSizepx,
									CanvasLocationX, CanvasLocationY-crabSpeed , CrabSizepx,CrabSizepx);
	}
}
